﻿using BuddHa.Common.CryptoOpex.RSAUtil.Implementation;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace BuddHa.Common.CryptoOpex.RSAUtil
{
    public class RSABuild
    {
        private static IRSAFormatter _rsaPkcs8 = new RSAPkcs8Formatter();
        private static IRSAFormatter _rsaPkcs1 = new RSAPkcs1Formatter();

        public static IRSADispatch BuildRSADispatch(string publicKey, string privateKey = "", EnumRSAFormt enumRSAFormt = EnumRSAFormt.Pkcs8, int size = (int)EnumRSAMode.RSA2)
        {
            if (string.IsNullOrEmpty(privateKey) && string.IsNullOrEmpty(publicKey))
            {
                throw new Exception("Build rsa disaptch faild!public and private keys must not be empty at the same time");
            }

            var rsaFormatter = enumRSAFormt == EnumRSAFormt.Pkcs8 ? _rsaPkcs8 : _rsaPkcs1;

            RSA privateRsa = null, publicRsa = null;
            if (!string.IsNullOrWhiteSpace(privateKey))
            {
                privateRsa = rsaFormatter.CreateByPrivateKey(privateKey, size);
            }
            if (!string.IsNullOrWhiteSpace(publicKey))
            {
                publicRsa = rsaFormatter.CreateByPublicKey(publicKey, size);
            }
            return new RSADispatch(privateRsa, publicRsa, Encoding.UTF8);
        }

        public static List<string> GeneratPkcs1(int size, bool format = false)
        {
            var keys = new List<string>();
            var kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
            kpGen.Init(new KeyGenerationParameters(new SecureRandom(), size));
            var keyPair = kpGen.GenerateKeyPair();
            var privateStringWriter = new StringWriter();
            var privatePemWriter = new PemWriter(privateStringWriter);
            privatePemWriter.WriteObject(keyPair.Private);
            privatePemWriter.Writer.Close();
            var privateKey = privateStringWriter.ToString();

            if (!format)
            {
                privateKey = privateKey.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r\n", "");
            }
            keys.Add(privateKey);

            var publicStringWriter = new StringWriter();
            var publicPemWriter = new PemWriter(publicStringWriter);
            publicPemWriter.WriteObject(keyPair.Public);
            publicPemWriter.Writer.Close();
            var publicKey = publicStringWriter.ToString();
            if (!format)
            {
                publicKey = publicKey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r\n", "");
            }

            keys.Add(publicKey);

            return keys;
        }

        public static List<string> Pkcs8Key(int keySize, bool format)
        {
            var keys = new List<string>();

            var kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
            kpGen.Init(new KeyGenerationParameters(new SecureRandom(), keySize));
            var keyPair = kpGen.GenerateKeyPair();

            var privateStringWriter = new StringWriter();
            var privatePemWriter = new PemWriter(privateStringWriter);
            var pkcs8 = new Pkcs8Generator(keyPair.Private);
            privatePemWriter.WriteObject(pkcs8);
            privatePemWriter.Writer.Close();
            string privateKey = privateStringWriter.ToString();

            if (!format)
            {
                privateKey = privateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r\n", "");
            }

            keys.Add(privateKey);

            var publicStringWriter = new StringWriter();
            var publicPemWriter = new PemWriter(publicStringWriter);
            publicPemWriter.WriteObject(keyPair.Public);
            publicPemWriter.Writer.Close();
            string publicKey = publicStringWriter.ToString();
            if (!format)
            {
                publicKey = publicKey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r\n", "");
            }

            keys.Add(publicKey);
            return keys;
        }
    }
}
